/*-------------------------------------------------------------------------
 *
 * block.h
 *	  POSTGRES 磁盘块定义。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/block.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef BLOCK_H
#define BLOCK_H

/*
 * 块编号：
 *
 * 每个数据文件（堆或索引）被划分为Postgres磁盘块
 * （可以认为是I/O的单位——一个Postgres缓冲区
 * 恰好包含一个磁盘块）。块的编号是顺序的，
 * 从0到0xFFFFFFFE。
 *
 * InvalidBlockNumber与bufmgr.h中的P_NEW是相同的。
 *
 * 访问方法、缓冲区管理器和存储管理器是
 * 几乎唯一应该直接访问磁盘块的代码部分。
 */
typedef uint32 BlockNumber;

#define InvalidBlockNumber		((BlockNumber) 0xFFFFFFFF)

#define MaxBlockNumber			((BlockNumber) 0xFFFFFFFE)

/*
 * 块ID：
 *
 * 这是块编号的存储类型。换句话说， 该类型
 * 用于磁盘结构（例如，在HeapTupleData中），而
 * 块编号是用于执行计算的类型（例如，
 * 在访问方法代码中）。
 *
 * 似乎没有理由将其分成不同的类型，除了
 * 块ID可以进行SHORTALIGN（因此包含它们的任意
 * 结构，如ItemPointerData，也可以进行SHORTALIGN）。
 * 这是减少每页行指针（ItemIdData）数组及
 * 每个堆或索引元组头部空间需求的重要考虑，
 * 因此在没有充分理由的情况下更改这一点似乎
 * 是不明智的。
 */
typedef struct BlockIdData
{
	uint16		bi_hi;
	uint16		bi_lo;
} BlockIdData;

typedef BlockIdData *BlockId;	/* 块标识符 */

/* ----------------
 *		支持宏
 * ----------------
 */

/*
 * BlockNumberIsValid
 *		True当且仅当blockNumber有效。
 */
#define BlockNumberIsValid(blockNumber) \
	((BlockNumber) (blockNumber) != InvalidBlockNumber)

/*
 * BlockIdIsValid
 *		True当且仅当块标识符有效。
 */
#define BlockIdIsValid(blockId) \
	PointerIsValid(blockId)

/*
 * BlockIdSet
 *		将块标识符设置为指定值。
 */
#define BlockIdSet(blockId, blockNumber) \
( \
	(blockId)->bi_hi = (blockNumber) >> 16, \
	(blockId)->bi_lo = (blockNumber) & 0xffff \
)

/*
 * BlockIdCopy
 *		复制块标识符。
 */
#define BlockIdCopy(toBlockId, fromBlockId) \
( \
	(toBlockId)->bi_hi = (fromBlockId)->bi_hi, \
	(toBlockId)->bi_lo = (fromBlockId)->bi_lo \
)

/*
 * BlockIdEquals
 *		检查块编号是否相等。
 */
#define BlockIdEquals(blockId1, blockId2) \
	((blockId1)->bi_hi == (blockId2)->bi_hi && \
	 (blockId1)->bi_lo == (blockId2)->bi_lo)

/*
 * BlockIdGetBlockNumber
 *		从块标识符中检索块编号。
 */
#define BlockIdGetBlockNumber(blockId) \
	((((BlockNumber) (blockId)->bi_hi) << 16) | ((BlockNumber) (blockId)->bi_lo))

#endif							/* BLOCK_H */
